package me.jessyan.mvparms.demo.util;


import android.os.Build;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;


import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.*;



/**
 * @author sh
 * @date 2019-07-31 11:13
 */
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public class CertificateUtils {

    private final static Charset CHARSET = StandardCharsets.UTF_8;



    /**
     * 创建签名
     * 注意：外部不要将timestamp、hotelId和sign这4个参数添加到方法参数params集合中
     * params就是请求的参数
     */
    public static String createSign(final HashMap<String, String> params, String hotelId, String secretKey, String timestamp) {
        //1、除去空值请求参数
        HashMap<String, String> newRequestParams = removeEmptyParam(params);

        //2、按照请求参数名的字母升序排列非空请求参数（包含hotelId,Timestamp)，使用URL键值对的格式（即key1=value1&key2=value2…）拼接成字符串
        newRequestParams.put("hotelId", hotelId);
        newRequestParams.put("Timestamp", timestamp);
        String strUrlParams = parseUrlString(newRequestParams);

        //4、最后拼接上secretKey得到字符串stringSignTemp
        String stringSignTemp = MessageFormat.format("{0}&SecretKey={1}", strUrlParams, secretKey);

        //5、对stringSignTemp进行MD5运算，并将得到的字符串所有字符转换为大写，得到sign值
        return DigestUtils.md5Hex(stringSignTemp.getBytes(CHARSET)).toUpperCase();
    }

    /**
     * 移除空请求参数
     */
    private static HashMap<String, String> removeEmptyParam(final HashMap<String, String> params) {
        HashMap<String, String> newParams = new HashMap<>(10);
        if (params == null || params.size() <= 0) {
            return newParams;
        }
        for (String key : params.keySet()) {
            String value = params.get(key);
            if (value == null || "".equals(value)) {
                continue;
            }
            newParams.put(key, value);
        }
        return newParams;
    }

    /**
     * 使用URL键值对的格式（即key1=value1&key2=value2…）将参数列表拼接成字符串
     */
    private static String parseUrlString(final HashMap<String, String> requestMap) {
        List<String> keyList = new ArrayList<>(requestMap.keySet());
        Collections.sort(keyList);

        List<String> entryList = new ArrayList<>();
        for (String key : keyList) {
            String value = requestMap.get(key);
            try {
                value = URLEncoder.encode(value, CHARSET.name());
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            entryList.add(MessageFormat.format("{0}={1}", key, value));
        }
        return TextUtils.join("&", entryList);
    }



    public static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

    public static String encodeHexString(final byte[] data) {
        final int l = data.length;
        final char[] out = new char[l << 1];
        // two characters form the hex value.
        for (int i = 0, j = 0; i < l; i++) {
            out[j++] = DIGITS_UPPER[(0xF0 & data[i]) >>> 4];
            out[j++] = DIGITS_UPPER[0x0F & data[i]];
        }
        return new String(out);
    }

    /**
     * 测试main 方法
     *
     * @param args
     */
    public static void main(String[] args) {
        // Body
        String params ="{\"deviceCode\":\"yzs82193\"}";
        HashMap<String,String> hashMap = new Gson().fromJson(params, new TypeToken<HashMap<String,String>>(){}.getType());
        String timestamp = String.valueOf(System.currentTimeMillis());
        String sign = createSign(hashMap, "shimao62ae0b32d0", "f6339f4974cacdeca4037489", timestamp);
        System.out.println("sign : " + sign);//sign : 483C62B944142944C8A8FBE593B00566
        System.out.println("timeMillis : " + timestamp);//timeMillis : 1636013711913
    }

}
